/**
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.solarchallenge.server.domain;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.solarchallenge.shared.ApplicationStatus;
import com.google.solarchallenge.shared.DocumentStatus;
import com.google.solarchallenge.shared.dtos.ApplicationDto;

import java.util.ArrayList;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

/**
 * Domain Object for Application.
 *
 * @author Arjun Satyapal
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION,
    detachable = "true")
public class ApplicationDao {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Long id;

  // Reference to Applicant.
  @Persistent
  private Key applicantKey;

  @Persistent
  private String applicationDetails;

  @Persistent(defaultFetchGroup = "true")
  private ApplicationStatus overallApplicationStatus;

  @Persistent
  private ArrayList<String> siteDiagramUrls = new ArrayList<String>();
  @Persistent
  private DocumentStatus siteDiagramStatus = DocumentStatus.NOT_SUBMITTED;

  @Persistent
  private ArrayList<String> electricalDiagramUrls = new ArrayList<String>();
  @Persistent
  private DocumentStatus electricalDiagramStatus = DocumentStatus.NOT_SUBMITTED;

  @Persistent
  private ArrayList<String> diagramNoteUrls = new ArrayList<String>();
  @Persistent
  private DocumentStatus diagramNoteStatus = DocumentStatus.NOT_SUBMITTED;

  public String getId() {
    return Long.toString(id);
  }

  public ApplicationStatus requiredApplicationStatus() {
    if (diagramNoteStatus == DocumentStatus.NOT_SUBMITTED ||
        electricalDiagramStatus == DocumentStatus.NOT_SUBMITTED ||
        siteDiagramStatus == DocumentStatus.NOT_SUBMITTED) {
      return ApplicationStatus.NOT_SUBMITTED;
    }

    if (diagramNoteStatus == DocumentStatus.APPLICANT_ATTENTION_REQUIRED ||
        electricalDiagramStatus == DocumentStatus.APPLICANT_ATTENTION_REQUIRED
        || siteDiagramStatus == DocumentStatus.APPLICANT_ATTENTION_REQUIRED) {
      return ApplicationStatus.APPLICANT_ATTENTION_REQUIRED;
    }

    // ApplicantAttention is given preference over underReview.
    if (diagramNoteStatus == DocumentStatus.UNDER_REVIEW ||
        electricalDiagramStatus == DocumentStatus.UNDER_REVIEW ||
        siteDiagramStatus == DocumentStatus.UNDER_REVIEW) {
      return ApplicationStatus.UNDER_REVIEW;
    }

    if (diagramNoteStatus == DocumentStatus.APPROVED &&
        electricalDiagramStatus == DocumentStatus.APPROVED &&
        siteDiagramStatus == DocumentStatus.APPROVED) {
      return ApplicationStatus.APPROVED;
    }

    // If all are in PendingReview, that means all the files are uploaded, and
    // user can click on
    // Submit which will take the status of all files to SUBMITTED_FOR_REVIEW.
    if (diagramNoteStatus == DocumentStatus.PENDING_REVIEW &&
        electricalDiagramStatus == DocumentStatus.PENDING_REVIEW &&
        siteDiagramStatus == DocumentStatus.PENDING_REVIEW) {
      return ApplicationStatus.READY_FOR_SUBMISSION;
    }

    throw new IllegalStateException(
        "Arguably should not reach here else some condition is missing. "
        + "Fix that. Some debuggin info : diagramNoteStatus["
        + diagramNoteStatus + "], electricalDiagramStatus["
        + electricalDiagramStatus + "], siteDiagramStatus["
        + siteDiagramStatus + "].");
  }

  public void updateOverallStatus() {
    setOverAllApplicationStatus(requiredApplicationStatus());
  }

  public String getEncodedApplicantKey() {
    return KeyFactory.keyToString(applicantKey);
  }

  public void setApplicantKey(String encodedKey) {
    this.applicantKey = KeyFactory.stringToKey(encodedKey);
  }

  public ArrayList<String> getSiteDiagramUrls() {
    return siteDiagramUrls;
  }

  public void setSiteDiagramUrls(ArrayList<String> siteDiagramUrls) {
    this.siteDiagramUrls = siteDiagramUrls;
  }

  public DocumentStatus getSiteDiagramStatus() {
    return siteDiagramStatus;
  }

  public void setSiteDiagramStatus(DocumentStatus siteDiagramStatus) {
    this.siteDiagramStatus = siteDiagramStatus;
    updateOverallStatus();
  }

  public ArrayList<String> getElectricalDiagramUrls() {
    return electricalDiagramUrls;
  }

  public void setElectricalDiagramUrls(
      ArrayList<String> electricalDiagramUrls) {
    this.electricalDiagramUrls = electricalDiagramUrls;
  }

  public DocumentStatus getElectricalDiagramStatus() {
    return electricalDiagramStatus;
  }

  public void setElectricalDiagramStatus(
      DocumentStatus electricalDiagramStatus) {
    this.electricalDiagramStatus = electricalDiagramStatus;
    updateOverallStatus();
  }

  public ArrayList<String> getDiagramNoteUrls() {
    return diagramNoteUrls;
  }

  public void setDiagramNoteUrls(ArrayList<String> diagramNoteUrls) {
    this.diagramNoteUrls = diagramNoteUrls;
  }

  public DocumentStatus getDiagramNoteStatus() {
    return diagramNoteStatus;
  }

  public void setDiagramNoteStatus(DocumentStatus diagramNoteStatus) {
    this.diagramNoteStatus = diagramNoteStatus;
    updateOverallStatus();
  }

  public String getApplicationDetails() {
    return applicationDetails;
  }

  public void setApplicationDetails(String applicationDetails) {
    this.applicationDetails = applicationDetails;
  }

  public ApplicationStatus getOverallApplicationStatus() {
    return overallApplicationStatus;
  }

  public void setOverAllApplicationStatus(
      ApplicationStatus overallApplicationStatus) {
    this.overallApplicationStatus = overallApplicationStatus;
  }

  public ApplicationDto toDto() {
    return new ApplicationDto.Builder().setId(id)
        .setApplicationDetails(applicationDetails)
        .setOverallApplicationDetails(overallApplicationStatus)
        .setApplicationDetails(applicationDetails)
        .setDiagramNoteStatus(diagramNoteStatus)
        .setDiagramNoteUrls(diagramNoteUrls)
        .setElectricalDiagramStatus(electricalDiagramStatus)
        .setElectricalDiagramUrls(electricalDiagramUrls)
        .setSiteDiagramStatus(siteDiagramStatus)
        .setSiteDiagramUrls(siteDiagramUrls).build();
  }
}
